#ifndef INC_MATERIAL_H_
#define INC_MATERIAL_H_

#pragma warning (disable : 4786 )

/*-<==>-----------------------------------------------------------------
/ Generic Material definition
/ Some materials will not use the position to define the diffuse or 
/ reflectance values
/----------------------------------------------------------------------*/
class CMaterial {
public:
	CMaterial() {}
	virtual ~CMaterial() {}
	virtual COLOR  getDiffuseColor(const VECTOR &loc) const = 0;
	virtual SCALAR getReflectance(const VECTOR &loc) const = 0;
	virtual  SCALAR getRefractionFactor(const VECTOR &loc)  const = 0;
	virtual  SCALAR getRefractionIndex(const VECTOR &loc)  const = 0;
	virtual SCALAR getDiffuseFactor(const VECTOR &loc)  const = 0;
	virtual SCALAR getAmbientalFactor(const VECTOR &loc)  const = 0;
	virtual SCALAR getSpecularFactor(const VECTOR &loc) const = 0;
	SCALAR getTurbulenceAddition(const VECTOR &loc, SCALAR aturbulence_factor) const;
	void bumpNormal(const VECTOR & loc, VECTOR& normal);
	bool bumpMap;
	void setBumpMap(bool value, SCALAR bump_factor);
	SCALAR bump_factor;
};

/*-<==>-----------------------------------------------------------------
/ A map, key is a std::string and the value is a material pointer
/----------------------------------------------------------------------*/
#include <map>
#include <string>
typedef std::map<std::string, CMaterial *> MMaterials;

/*-<==>-----------------------------------------------------------------
/ Solid color material
/----------------------------------------------------------------------*/
class CSolidMaterial : public CMaterial {
protected:
	COLOR  diffuse_color;
	SCALAR reflectance_factor;
	SCALAR refraction_factor;
	SCALAR refraction_index;
	SCALAR diffuse_factor;
	SCALAR ambiental_factor;
	SCALAR specular_factor;


public:
	CSolidMaterial(const COLOR &diffuse, SCALAR reflectance,SCALAR refraction,SCALAR refractionI,  SCALAR aambiental_factor,SCALAR adiffuse_factor,SCALAR aspecular_factor);
	virtual COLOR  getDiffuseColor(const VECTOR &loc) const;
	SCALAR getReflectance(const VECTOR &loc)  const;
	SCALAR getDiffuseFactor(const VECTOR &loc)  const;
	SCALAR getRefractionFactor(const VECTOR &loc)  const;
	SCALAR getRefractionIndex(const VECTOR &loc)  const;
	SCALAR getAmbientalFactor(const VECTOR &loc)  const;
	SCALAR getSpecularFactor(const VECTOR &loc) const;
};


/*-<==>-----------------------------------------------------------------
/ Composed material
/----------------------------------------------------------------------*/
class CCheckerMaterial : public CMaterial {
	CMaterial *tile_white;
	CMaterial *tile_black;
	SCALAR     side_size;
	bool is_white(const VECTOR &loc) const;
public:
	CCheckerMaterial (CMaterial *white, CMaterial *black, SCALAR size);
	COLOR  getDiffuseColor(const VECTOR &loc) const;
	SCALAR getReflectance(const VECTOR &loc) const;
	SCALAR getDiffuseFactor(const VECTOR &loc)  const;
	SCALAR getRefractionFactor(const VECTOR &loc)  const;
	SCALAR getRefractionIndex(const VECTOR &loc)  const;
	SCALAR getAmbientalFactor(const VECTOR &loc)  const;
	SCALAR getSpecularFactor(const VECTOR &loc) const;
};


/*-<==>-----------------------------------------------------------------
/ Turbulence Material
/----------------------------------------------------------------------*/
class CTurbMaterial : public CSolidMaterial {
	float turbulence_factor;
public:
	CTurbMaterial (const COLOR &diffuse, SCALAR reflectance,SCALAR refraction,SCALAR refractionI,  SCALAR aambiental_factor,SCALAR adiffuse_factor,SCALAR aspecular_factor, float aturbulence_factor);
	COLOR getDiffuseColor(const VECTOR &loc) const;
};

/*-<==>-----------------------------------------------------------------
/ Marble Material
/----------------------------------------------------------------------*/
class CMarbleMaterial : public CSolidMaterial {
	SCALAR period; //repetition lines +- 5
	SCALAR power; //twists +- 5
	SCALAR turb_size; //turbulence +- 36
public:
	CMarbleMaterial (const COLOR &diffuse, SCALAR reflectance,SCALAR refraction,SCALAR refractionI,  SCALAR aambiental_factor,SCALAR adiffuse_factor,SCALAR aspecular_factor);
	void setMarbleParams(SCALAR aperiod, SCALAR apower, SCALAR aturb_size);
	COLOR getDiffuseColor(const VECTOR &loc) const;
};


/*-<==>-----------------------------------------------------------------
/ Wood Material
/----------------------------------------------------------------------*/
class CWoodMaterial : public CSolidMaterial {
	SCALAR turb_size; 
public:
	CWoodMaterial (const COLOR &diffuse, SCALAR reflectance,SCALAR refraction,SCALAR refractionI,  SCALAR aambiental_factor,SCALAR adiffuse_factor,SCALAR aspecular_factor);
	void setWoodParams(SCALAR aturb_size);
	COLOR getDiffuseColor(const VECTOR &loc) const;
};

#endif